package MyGui;

import java.awt.*;
import java.awt.event.*;
import javax.swing.border.*;
import java.lang.Integer;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
import java.util.*;
import java.text.*;


import DistSys.*;
import Element.*;
import Element.Geom.*;

/**
 * The class <code>LossSumDlg</code> implements the loss summary dialog.
 * @author  Christian Krane, ABB Inc.
 * @version 1.0, 02/23/02
 */

public class LossSumDlg extends MyDlgFrame implements ActionListener {

    JLabel[]  labels;
    final int NUM_LABEL =14;
    final int NUM_CUST=0,DEMAND_KVA=1,DEMAND_KW=2,CAPITAL_COST=3,OM_COST=4,
              WORST_DROP=5,WORST_ANGLE=6,LINE_LOSS=7,CABLE_LOSS=8,CORE_LOSS=9,
              WINDING_LOSS=10,OTHER_LOSS=11,TOTAL_LOSS=12,TOTAL_LOSS_PERCENT=13;

    private JButton      btnPerformAnalysis;
    private ZoneComboBox comboZone;

    public LossSumDlg(MainFrame parent, String title) {
        super(parent, title);
        setSize(400,240);

        //layout of form
        Container contentPane = getContentPane();
        contentPane.setLayout(new BorderLayout(0,0));
        JPanel centralPanel = new JPanel();
        centralPanel.setLayout(new GridLayout(1, 2, GAP, 0));
        contentPane.add(centralPanel, BorderLayout.CENTER);

        // create all fields that show the calculated values
        labels= new JLabel[NUM_LABEL];
        for(int i=0;i<NUM_LABEL;i++){
            // "--" is overwritten by performAnalysis ()
            labels[i] = new JLabel("--");
            labels[i].setAlignmentX( JLabel.RIGHT_ALIGNMENT);
            labels[i].setForeground(Color.blue);
        }

        // create the different panels
        JPanel topPanel = createTopPanel();
        JPanel generalPanel = createGeneralPanel();
        JPanel lossesPanel = createLossesPanel ();

        // insert the different panels in layout
        contentPane.add(topPanel,BorderLayout.NORTH);
        centralPanel.add(generalPanel);
        centralPanel.add(lossesPanel);

        // perform Loss Summary Analysis
        performAnalysis ();
    } // end of constructor

    private JPanel createTopPanel(){
        JPanel p = new JPanel();
        p.setLayout(gridBagLayout);

        JLabel selectZone=new JLabel("Area:");
        add(p, selectZone, 0,0,1,1,0,0,GridBagConstraints.WEST,
            GridBagConstraints.NONE,GAP,GAP,GAP,GAP);
        comboZone=new ZoneComboBox();
        add(p, comboZone, 1,0,1,1,100,0,GridBagConstraints.WEST,
            GridBagConstraints.HORIZONTAL,GAP,0,GAP,GAP);
        btnPerformAnalysis = new JButton ("Perform Analysis");
        btnPerformAnalysis.setEnabled(true);
        btnPerformAnalysis.setMnemonic('P');
        btnPerformAnalysis.addActionListener(this);
        add(p, btnPerformAnalysis, 2,0,1,1,0,0,GridBagConstraints.EAST,
            GridBagConstraints.NONE,GAP,0,GAP,GAP);
        return p;
    }

    private JPanel createGeneralPanel(){
        JPanel p = new JPanel(gridBagLayout);
        p.setBorder( new TitledBorder(" General Information "));

        JLabel lblOne = new JLabel("No. of Customers:");
        JLabel lblTwo = new JLabel("Demand(kVA):");
        JLabel lblThree=new JLabel("Demand(kW):");
        JLabel lblFour =new JLabel("Capital Cost($):");
        JLabel lblFive =new JLabel("OM Cost ($/yr):");
        JLabel lblSix = new JLabel("Worst % Drop:");
        JLabel lblSeven=new JLabel("Worst Angle:");

        add(p,lblOne,0,0,1,1,0,0,GridBagConstraints.WEST,GridBagConstraints.NONE,0,GAP,0,0);
        add(p,labels[NUM_CUST],1,0,1,1,100,0,GridBagConstraints.EAST,GridBagConstraints.NONE,0,0,0,GAP);
        add(p,lblTwo,0,1,1,1,0,0,GridBagConstraints.WEST,GridBagConstraints.NONE,0,GAP,0,0);
        add(p,labels[DEMAND_KVA],1,1,1,1,100,0,GridBagConstraints.EAST,GridBagConstraints.NONE,0,0,0,GAP);
        add(p,lblThree,0,2,1,1,0,0,GridBagConstraints.WEST,GridBagConstraints.NONE,0,GAP,0,0);
        add(p,labels[DEMAND_KW],1,2,1,1,100,0,GridBagConstraints.EAST,GridBagConstraints.NONE,0,0,0,GAP);
        add(p,lblFour,0,3,1,1,0,0,GridBagConstraints.WEST,GridBagConstraints.NONE,GAP,GAP,0,0);
        add(p,labels[CAPITAL_COST],1,3,1,1,100,0,GridBagConstraints.EAST,GridBagConstraints.NONE,GAP,0,0,GAP);
        add(p,lblFive,0,4,1,1,0,0,GridBagConstraints.WEST,GridBagConstraints.NONE,0,GAP,0,0);
        add(p,labels[OM_COST],1,4,1,1,100,0,GridBagConstraints.EAST,GridBagConstraints.NONE,0,0,0,GAP);
        add(p,lblSix,0,5,1,1,0,0,GridBagConstraints.WEST,GridBagConstraints.NONE,GAP,GAP,0,0);
        add(p,labels[WORST_DROP],1,5,1,1,100,0,GridBagConstraints.EAST,GridBagConstraints.NONE,GAP,0,0,GAP);
        add(p,lblSeven,0,6,1,1,0,100,GridBagConstraints.NORTHWEST,GridBagConstraints.NONE,0,GAP,0,0);
        add(p,labels[WORST_ANGLE],1,6,1,1,100,100,GridBagConstraints.NORTHEAST,GridBagConstraints.NONE,0,0,0,GAP);
        return p;
    }

    private JPanel createLossesPanel(){
        JPanel p = new JPanel(gridBagLayout);
        p.setBorder( new TitledBorder(" Losses (kW) "));

        JLabel lblOne = new JLabel("Line Losses:");
        JLabel lblTwo = new JLabel("Cable Losses:");
        JLabel lblThree=new JLabel("Core Losses:");
        JLabel lblFour =new JLabel("Winding Losses:");
        JLabel lblFive =new JLabel("Other Losses:");
        JLabel lblSix =new JLabel("Total Losses:");
        JLabel lblSeven =new JLabel("% Total Losses:");

        add(p,lblOne,0,0,1,1,0,0,GridBagConstraints.WEST,GridBagConstraints.NONE,0,GAP,0,0);
        add(p,labels[LINE_LOSS],1,0,1,1,100,0,GridBagConstraints.EAST,GridBagConstraints.NONE,0,0,0,GAP);
        add(p,lblTwo,0,1,1,1,0,0,GridBagConstraints.WEST,GridBagConstraints.NONE,0,GAP,0,0);
        add(p,labels[CABLE_LOSS],1,1,1,1,100,0,GridBagConstraints.EAST,GridBagConstraints.NONE,0,0,0,GAP);
        add(p,lblThree,0,2,1,1,0,0,GridBagConstraints.WEST,GridBagConstraints.NONE,0,GAP,0,0);
        add(p,labels[CORE_LOSS],1,2,1,1,100,0,GridBagConstraints.EAST,GridBagConstraints.NONE,0,0,0,GAP);
        add(p,lblFour,0,3,1,1,0,0,GridBagConstraints.WEST,GridBagConstraints.NONE,0,GAP,0,0);
        add(p,labels[WINDING_LOSS],1,3,1,1,100,0,GridBagConstraints.EAST,GridBagConstraints.NONE,0,0,0,GAP);
        add(p,lblFive,0,4,1,1,0,0,GridBagConstraints.WEST,GridBagConstraints.NONE,0,GAP,GAP,0);
        add(p,labels[OTHER_LOSS],1,4,1,1,100,0,GridBagConstraints.EAST,GridBagConstraints.NONE,0,0,GAP,GAP);
        add(p,lblSix,0,5,1,1,0,0,GridBagConstraints.WEST,GridBagConstraints.NONE,GAP,GAP,0,0);
        add(p,labels[TOTAL_LOSS],1,5,1,1,100,0,GridBagConstraints.EAST,GridBagConstraints.NONE,GAP,0,0,GAP);
        add(p,lblSeven,0,6,1,1,0,100,GridBagConstraints.NORTHWEST,GridBagConstraints.NONE,0,GAP,0,0);
        add(p,labels[TOTAL_LOSS_PERCENT],1,6,1,1,100,100,GridBagConstraints.NORTHEAST,GridBagConstraints.NONE,0,0,0,GAP);
        return p;
    }


    public void actionPerformed (ActionEvent evt) {
        Object source = evt.getSource();
        if (source==btnPerformAnalysis)
            performAnalysis();
    }

    private void performAnalysis() {
        double numberCustomers=0;
        double demandKVA=0;
        double demandKW=0;
        double capitalCosts=0;
        double omCosts=0;
        double worstDrop=0;
        double worstAngle=0;
        double lineLosses=0;
        double cableLosses=0;
        double coreLosses=0;
        double windingLosses=0;
        double otherLosses=0;
        double totalLosses=0;
        double ptotalLosses=0;

        // get the selected zone in the ComboBox
        double dZone;
        try {   // ...class ZoneComboBox might throw an exception due to an invalid zone
            dZone = comboZone.getSelectedZone();
        } catch(ZoneComboBox.ZoneException e) {
            JOptionPane.showMessageDialog(getParent(),
                "'" + e.getMessage() + "' is not a valid zone.");
            return;
        }

        // Summarize every element ...
        for (int i = 0; i < Sys.elemList.size(); i++) {
            AbsElem elem = (AbsElem)Sys.elemList.elementAt(i);
            AbsElemGeom geom = elem.getElemGeomObj();

            // ... if it fits the specified zone in the ComboBox
            if (Zone.getZoneFits(dZone, elem)) {
                //ReliaInd relia = elem.getReliaIndObj();
                //CktLaw ckt = elem.getCktLawObj();

                // The m multiplier equals the length for lines and cables, 1 otherwise
                double m = 1.0;
                if (elem instanceof Line)
                    m = ((Line)elem).getLength();

                // Costumer Data is added up
                if (elem instanceof Load) {
                    numberCustomers += elem.getData(AbsElem.DATA_CUSTOMERS);
                    demandKVA += elem.getData(AbsElem.DATA_CONST_POWER);
                    demandKW += (elem.getData(AbsElem.DATA_CONST_POWER) *
                                elem.getData(AbsElem.DATA_PF_CONST_POWER));
                }

                // Capital Costs and OM Costs are added up
                capitalCosts += elem.getData(AbsElem.DATA_CAPITAL_COST) * m;
                omCosts += elem.getData(AbsElem.DATA_OM_COST) * m;

                // Worst Voltage Drop and Worst Angle
                if (elem instanceof Load && elem.getResult(AbsElem.RES_VOLT_DROP) > worstDrop)
                    worstDrop = elem.getResult(AbsElem.RES_VOLT_DROP);
                if (elem instanceof Load && Math.abs(elem.getResult(AbsElem.RES_VOLT_ANG)) > Math.abs(worstAngle))
                    worstAngle = elem.getResult(AbsElem.RES_VOLT_ANG);

                //  Losses are calculated for each element
                double dVoltage, dPhases = elem.getData(AbsElem.DATA_PHASE);
                if (dPhases == 0.0)
                    dPhases = 3.0;
                // WARNING: This needs to be reviewed for non-radial systems.
                if (geom.parent != null)
                    dVoltage = geom.parent.getResult(AbsElem.RES_VOLT_MAG);
                else
                    dVoltage = elem.getResult(AbsElem.RES_VOLT_MAG);
                // (Unit: A * A * Ohm / 1000 = A * V / 1000 = W / 1000 = kW)
                double dSeriesLosses = dPhases *
                    elem.getResult(AbsElem.RES_CURR_MAG )*
                    elem.getResult(AbsElem.RES_CURR_MAG )*
                    elem.getData(AbsElem.DATA_RESISTANCE) * m / 1000;
                // (Unit: kV * kV * 1/Ohm * 1000 = kV * kA * 1000 = MW * 1000 = kW)
                double dShuntLosses = dPhases * dVoltage * dVoltage *
                    elem.getData(AbsElem.DATA_SHUNT_COND) * m * 1000 / 3;

                // Losses are added up
                if (elem instanceof Line) {
                    if (((LineGeom)geom).getIsCable())
                        cableLosses += (dSeriesLosses * geom.ubzMult[elem.getPhase()]);  // for unbalanced phasing
                    else
                        lineLosses += (dSeriesLosses * geom.ubzMult[elem.getPhase()]); // for unbalanced phasing
                    otherLosses += dShuntLosses;
                } else if (elem instanceof Txfm || elem instanceof Regulator) {
                    windingLosses += dSeriesLosses;
                    coreLosses += dShuntLosses;
                } else   // other
                    otherLosses += (dSeriesLosses + dShuntLosses);
            } // end of (if zone fits)
        } // end of for-loop

        // calculation of Total Losses
        totalLosses = lineLosses + cableLosses + windingLosses + coreLosses + otherLosses;
        if (demandKW > 0) ptotalLosses = totalLosses / demandKW * 100;

        // graphical output...set output format
        NumberFormat integerFormat = NumberFormat.getNumberInstance();
        integerFormat.setMaximumFractionDigits(0);
        NumberFormat doubleFormat = NumberFormat.getNumberInstance();
        doubleFormat.setMaximumFractionDigits(2);
        doubleFormat.setMinimumFractionDigits(2);

        // graphical output of calculated data
        labels[NUM_CUST].setText(integerFormat.format (numberCustomers));
        labels[DEMAND_KVA].setText(integerFormat.format (demandKVA));
        labels[DEMAND_KW].setText(integerFormat.format (demandKW));
        labels[CAPITAL_COST].setText(integerFormat.format (capitalCosts));
        labels[OM_COST].setText(integerFormat.format (omCosts));
        labels[WORST_DROP].setText(doubleFormat.format (worstDrop));
        labels[WORST_ANGLE].setText(doubleFormat.format (worstAngle));
        labels[LINE_LOSS].setText(doubleFormat.format (lineLosses));
        labels[CABLE_LOSS].setText(doubleFormat.format (cableLosses));
        labels[CORE_LOSS].setText(doubleFormat.format (coreLosses));
        labels[WINDING_LOSS].setText(doubleFormat.format (windingLosses));
        labels[OTHER_LOSS].setText(doubleFormat.format (otherLosses));
        labels[TOTAL_LOSS].setText(doubleFormat.format (totalLosses));
        labels[TOTAL_LOSS_PERCENT].setText(doubleFormat.format (ptotalLosses));
    } // performAnalysis ()
}// class
